package cn.iocoder.yudao.module.vr.service.testoption;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.vr.controller.admin.test.vo.TestOption;
import cn.iocoder.yudao.module.vr.controller.admin.testoption.vo.*;
import cn.iocoder.yudao.module.vr.convert.testoption.TestOptionConvert;
import cn.iocoder.yudao.module.vr.dal.dataobject.testoption.TestOptionDO;
import cn.iocoder.yudao.module.vr.dal.mysql.testoption.TestOptionMapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.vr.enums.ErrorCodeConstants.*;

/**
 * 试题选项 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class TestOptionServiceImpl implements TestOptionService {

    @Resource
    private TestOptionMapper testOptionMapper;

    @Override
    public Long createTestOption(TestOptionCreateReqVO createReqVO) {
        // 插入
        TestOptionDO testOption = TestOptionConvert.INSTANCE.convert(createReqVO);
        testOptionMapper.insert(testOption);
        // 返回
        return testOption.getId();
    }

    @Override
    public void createOptionsFormTest(Long testId, List<TestOption> testOptions) {
        for (TestOption testOption : testOptions) {
            TestOptionDO optionDO = new TestOptionDO();
            optionDO.setTestId(testId);
            optionDO.setOrderId(testOption.getOrderId());
            optionDO.setContent(testOption.getContent());
            optionDO.setPictureUrl(testOption.getPicture());
            optionDO.setCorrect(testOption.isCorrect());
            testOptionMapper.insert(optionDO);
        }
    }

    @Override
    public void updateTestOption(TestOptionUpdateReqVO updateReqVO) {
        // 校验存在
        validateTestOptionExists(updateReqVO.getId());
        // 更新
        TestOptionDO updateObj = TestOptionConvert.INSTANCE.convert(updateReqVO);
        testOptionMapper.updateById(updateObj);
    }

    @Override
    public void updateTestOptionsFromTest(Long testId, List<TestOption> testOptions) {
        List<TestOptionDO> testOptionDOList = testOptionMapper.selectListByTestId(testId);
        Map<Long, TestOptionDO> optionDOMap = testOptionDOList.stream().collect(Collectors.toMap(TestOptionDO::getId, gap -> gap));
        List<TestOption> createOptions = new ArrayList<>();
        for (TestOption testOption : testOptions) {
            if (testOption.getId() == null || testOption.getId() == 0) {
                createOptions.add(testOption);
            } else {
                validateTestOptionExists(testOption.getId());
                TestOptionDO optionDO = optionDOMap.get(testOption.getId());
                optionDO.setContent(testOption.getContent());
                optionDO.setOrderId(testOption.getOrderId());
                optionDO.setCorrect(testOption.isCorrect());
                optionDO.setPictureUrl(testOption.getPicture());
                testOptionMapper.updateById(optionDO);
                optionDOMap.remove(testOption.getId());
            }
        }
        if (!createOptions.isEmpty()) {
            createOptionsFormTest(testId, createOptions);
        }
        if (!optionDOMap.isEmpty()) {
            optionDOMap.keySet().forEach(this::deleteTestOption);
        }
    }

    @Override
    public List<TestOption> getTestOptionListByTestId(Long testId) {
        List<TestOptionDO> testOptionDOS = testOptionMapper.selectListByTestId(testId);
        List<TestOption> testOptions = new ArrayList<>();
        for (TestOptionDO testOptionDO : testOptionDOS) {
            TestOption testOption = new TestOption(testOptionDO.getId()
                    , testOptionDO.getTestId()
                    , testOptionDO.getOrderId()
                    , testOptionDO.getContent()
                    , testOptionDO.getPictureUrl()
                    , testOptionDO.getCorrect());
            testOptions.add(testOption);
        }
        testOptions.sort(Comparator.comparing(TestOption::getOrderId));
        return testOptions;
    }

    @Override
    public void deleteTestOption(Long id) {
        // 校验存在
        validateTestOptionExists(id);
        // 删除
        testOptionMapper.deleteById(id);
    }

    private void validateTestOptionExists(Long id) {
        if (testOptionMapper.selectById(id) == null) {
            throw exception(TEST_NOT_EXISTS);
        }
    }

    @Override
    public TestOptionDO getTestOption(Long id) {
        return testOptionMapper.selectById(id);
    }

    @Override
    public List<TestOptionDO> getTestOptionList(Collection<Long> ids) {
        return testOptionMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<TestOptionDO> getTestOptionPage(TestOptionPageReqVO pageReqVO) {
        return testOptionMapper.selectPage(pageReqVO);
    }

    @Override
    public List<TestOptionDO> getTestOptionList(TestOptionExportReqVO exportReqVO) {
        return testOptionMapper.selectList(exportReqVO);
    }

}
